package com.snow.useviewdemo.util.statusbar;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ScrollView;

import androidx.appcompat.widget.Toolbar;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment;

import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;

/**
 * After kitkat add fake status bar
 * Created by qiu on 8/27/16.
 */
@TargetApi(Build.VERSION_CODES.KITKAT)
class StatusBarCompatKitKat {

    private static final String TAG_FAKE_STATUS_BAR_VIEW = "statusBarView";
    private static final String TAG_MARGIN_ADDED = "marginAdded";

    /**
     * return statusBar's Height in pixels
     */
    private static int getStatusBarHeight(Context context) {
        int result = 0;
        int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resId > 0) {
            result = context.getResources().getDimensionPixelOffset(resId);
        }
        return result;
    }

    /**
     * 1. Add fake statusBarView.
     * 2. set tag to statusBarView.
     */
    private static View addFakeStatusBarView(Activity activity, int statusBarColor, int statusBarHeight) {
        Window window = activity.getWindow();
        ViewGroup mDecorView = (ViewGroup) window.getDecorView();

        View mStatusBarView = new View(activity);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight);
        layoutParams.gravity = Gravity.TOP;
        mStatusBarView.setLayoutParams(layoutParams);
        mStatusBarView.setBackgroundColor(statusBarColor);
        mStatusBarView.setTag(TAG_FAKE_STATUS_BAR_VIEW);

        mDecorView.addView(mStatusBarView);
        return mStatusBarView;
    }

    /**
     * use reserved order to remove is more quickly.
     */
    private static void removeFakeStatusBarViewIfExist(Activity activity) {
        Window window = activity.getWindow();
        ViewGroup mDecorView = (ViewGroup) window.getDecorView();

        View fakeView = mDecorView.findViewWithTag(TAG_FAKE_STATUS_BAR_VIEW);
        if (fakeView != null) {
            mDecorView.removeView(fakeView);
        }
    }

    /**
     * add marginTop to simulate set FitsSystemWindow true
     */
    private static void addMarginTopToContentChild(View mContentChild, int statusBarHeight) {
        if (mContentChild == null) {
            return;
        }
        if (!TAG_MARGIN_ADDED.equals(mContentChild.getTag())) {
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams();
            lp.topMargin += statusBarHeight;
            mContentChild.setLayoutParams(lp);
            mContentChild.setTag(TAG_MARGIN_ADDED);
        }
    }

    /**
     * remove marginTop to simulate set FitsSystemWindow false
     */
    private static void removeMarginTopOfContentChild(View mContentChild, int statusBarHeight) {
        if (mContentChild == null) {
            return;
        }
        if (TAG_MARGIN_ADDED.equals(mContentChild.getTag())) {
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams();
            lp.topMargin -= statusBarHeight;
            mContentChild.setLayoutParams(lp);
            mContentChild.setTag(null);
        }
    }

    /**
     * set StatusBarColor
     * <p>
     * 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
     * 2. removeFakeStatusBarViewIfExist
     * 3. addFakeStatusBarView
     * 4. addMarginTopToContentChild
     * 5. cancel ContentChild's fitsSystemWindow
     */
    static void setStatusBarColor(Activity activity, int statusColor) {
        Window window = activity.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = window.findViewById(Window.ID_ANDROID_CONTENT);
        View mContentChild = mContentView.getChildAt(0);
        int statusBarHeight = getStatusBarHeight(activity);

        removeFakeStatusBarViewIfExist(activity);
        addFakeStatusBarView(activity, statusColor, statusBarHeight);
        addMarginTopToContentChild(mContentChild, statusBarHeight);

        if (mContentChild != null) {
            ViewCompat.setFitsSystemWindows(mContentChild, false);
        }
    }

    /**
     * set StatusBarColor
     * <p>
     * 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
     * 2. removeFakeStatusBarViewIfExist
     * 3. addFakeStatusBarView
     * 4. addMarginTopToContentChild
     * 5. cancel ContentChild's fitsSystemWindow
     */
    static void setStatusBarGradientColor(Activity activity, int drawableResource) {
        Window window = activity.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = activity.findViewById(android.R.id.content);
        View mContentChild = mContentView.getChildAt(0);
        if (mContentChild instanceof StatusBarView) {
            mContentChild.setBackgroundResource(drawableResource);
        } else {
            mContentChild.setPadding(0, getStatusBarHeight(activity), 0, 0);
            mContentChild = new StatusBarView(activity);
            LinearLayout.LayoutParams params =
                    new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
            mContentChild.setLayoutParams(params);
            mContentChild.setBackgroundResource(drawableResource);
            mContentView.addView(mContentChild);
        }
        removeFakeStatusBarViewIfExist(activity);
        removeMarginTopOfContentChild(mContentChild, getStatusBarHeight(activity));
        if (mContentChild != null) {
            ViewCompat.setFitsSystemWindows(mContentChild, false);
        }
    }

    /**
     * translucentStatusBar
     * <p>
     * 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
     * 2. removeFakeStatusBarViewIfExist
     * 3. removeMarginTopOfContentChild
     * 4. cancel ContentChild's fitsSystemWindow
     */
    static void translucentStatusBarForImage(Activity activity) {
        Window window = activity.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = activity.findViewById(Window.ID_ANDROID_CONTENT);
        View mContentChild = mContentView.getChildAt(0);
        if (mContentView.getChildAt(mContentView.getChildCount() - 1) instanceof StatusBarView) {
            mContentView.removeView(mContentView.getChildAt(mContentView.getChildCount() - 1));
            mContentChild.setPadding(0, 0, 0, 0);
        }
        removeFakeStatusBarViewIfExist(activity);
        removeMarginTopOfContentChild(mContentChild, getStatusBarHeight(activity));
        if (mContentChild != null) {
            ViewCompat.setFitsSystemWindows(mContentChild, false);
        }
    }

    /**
     * translucentStatusBar
     * <p>
     * 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
     * 2. removeFakeStatusBarViewIfExist
     * 3. removeMarginTopOfContentChild
     * 4. cancel ContentChild's fitsSystemWindow
     */
    static void translucentStatusBar(Activity activity) {
        Window window = activity.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = activity.findViewById(Window.ID_ANDROID_CONTENT);
        View mContentChild = mContentView.getChildAt(0);
        if (mContentView.getChildAt(mContentView.getChildCount() - 1) instanceof StatusBarView)
            mContentView.removeView(mContentView.getChildAt(mContentView.getChildCount() - 1));
        else
            mContentChild.setPadding(mContentChild.getPaddingLeft(), mContentChild.getPaddingTop() + getStatusBarHeight(activity), mContentChild.getPaddingRight(), mContentChild.getPaddingBottom());//添加statusbar高度
        removeFakeStatusBarViewIfExist(activity);
        removeMarginTopOfContentChild(mContentChild, getStatusBarHeight(activity));
        if (mContentChild != null) {
            ViewCompat.setFitsSystemWindows(mContentChild, false);
        }
    }

    /**
     * @param activity
     * @param bgView   需要沉浸的View
     */
    static void translucentStatusBar(Activity activity, View bgView) {
        Window window = activity.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = activity.findViewById(Window.ID_ANDROID_CONTENT);
        if (mContentView.getChildAt(mContentView.getChildCount() - 1) instanceof StatusBarView)
            mContentView.removeView(mContentView.getChildAt(mContentView.getChildCount() - 1));
        else
            bgView.setPadding(bgView.getPaddingLeft(), bgView.getPaddingTop() + getStatusBarHeight(activity), bgView.getPaddingRight(), bgView.getPaddingBottom());//添加statusbar高度
        removeFakeStatusBarViewIfExist(activity);
        removeMarginTopOfContentChild(bgView, getStatusBarHeight(activity));
        if (bgView != null) {
            ViewCompat.setFitsSystemWindows(bgView, false);
        }
    }

    /**
     * translucentStatusBar for fragment
     *
     * @param fragment
     */
    static void translucentStatusBarForFragment(Fragment fragment) {
        Window window = fragment.getActivity().getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = fragment.getActivity().findViewById(android.R.id.content);
        if (mContentView != null) {
            View rootView;
            rootView = mContentView.getChildAt(mContentView.getChildCount() - 1);
            if (rootView instanceof StatusBarView) {
                mContentView.removeView(rootView);
                mContentView.setPadding(0, 0, 0, 0);
            }
            if (mContentView.getChildAt(0) != null) {
                mContentView.getChildAt(0).setPadding(0, 0, 0, 0);
            }
        }

        removeFakeStatusBarViewIfExist(fragment.getActivity());
        removeMarginTopOfContentChild(mContentView, getStatusBarHeight(fragment.getActivity()));
        View view = fragment.getView();
        if (view != null) {
            if (view instanceof ScrollView) {
                ViewGroup viewGroup = (ViewGroup) view;
                View childAt = viewGroup.getChildAt(0);
                if (childAt != null) {
                    childAt.setPadding(childAt.getPaddingLeft(), childAt.getPaddingTop() + getStatusBarHeight(fragment.getContext()), childAt.getPaddingRight(), childAt.getPaddingBottom());
                }
            } else {
                view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + getStatusBarHeight(fragment.getContext()), view.getPaddingRight(), view.getPaddingBottom());
            }
            ViewCompat.setFitsSystemWindows(view, false);
        }
    }

    /**
     * @param fragment
     * @param bgView
     */
    static void translucentStatusBarForFragment(Fragment fragment, View bgView) {
        Window window = fragment.getActivity().getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = fragment.getActivity().findViewById(android.R.id.content);
        if (mContentView != null) {
            View rootView;
            rootView = mContentView.getChildAt(mContentView.getChildCount() - 1);
            if (rootView instanceof StatusBarView) {
                mContentView.removeView(rootView);
                mContentView.setPadding(0, 0, 0, 0);
            }
            if (mContentView.getChildAt(0) != null) {
                mContentView.getChildAt(0).setPadding(0, 0, 0, 0);
            }
        }

        removeFakeStatusBarViewIfExist(fragment.getActivity());
        removeMarginTopOfContentChild(mContentView, getStatusBarHeight(fragment.getActivity()));
//        View view = fragment.getView();
//        if (view != null) {
//            if (view instanceof ScrollView) {
//                ViewGroup viewGroup = (ViewGroup) view;
//                View childAt = viewGroup.getChildAt(0);
//                if (childAt != null) {
//                    childAt.setPadding(childAt.getPaddingLeft(), childAt.getPaddingTop() + getStatusBarHeight(fragment.getContext()), childAt.getPaddingRight(), childAt.getPaddingBottom());
//                }
//            } else {
//                view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + getStatusBarHeight(fragment.getContext()), view.getPaddingRight(), view.getPaddingBottom());
//            }
//            ViewCompat.setFitsSystemWindows(view, false);
//        }
        bgView.setPadding(bgView.getPaddingLeft(), bgView.getPaddingTop() + getStatusBarHeight(fragment.getContext()), bgView.getPaddingRight(), bgView.getPaddingBottom());
        ViewCompat.setFitsSystemWindows(bgView, false);
    }

    /**
     * compat for CollapsingToolbarLayout
     * <p>
     * 1. set Window Flag : WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
     * 2. set FitsSystemWindows for views.
     * 3. add Toolbar's height, let it layout from top, then add paddingTop to layout normal.
     * 4. removeFakeStatusBarViewIfExist
     * 5. removeMarginTopOfContentChild
     * 6. add OnOffsetChangedListener to change statusBarView's alpha
     */

    static void setStatusBarColorForCollapsingToolbar(Activity activity, final AppBarLayout appBarLayout, final CollapsingToolbarLayout collapsingToolbarLayout,
                                                      Toolbar toolbar, int statusColor) {
        Window window = activity.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        ViewGroup mContentView = window.findViewById(Window.ID_ANDROID_CONTENT);

        View mContentChild = mContentView.getChildAt(0);
        mContentChild.setFitsSystemWindows(false);
        ((View) appBarLayout.getParent()).setFitsSystemWindows(false);
        appBarLayout.setFitsSystemWindows(false);
        collapsingToolbarLayout.setFitsSystemWindows(false);
        collapsingToolbarLayout.getChildAt(0).setFitsSystemWindows(false);

        toolbar.setFitsSystemWindows(false);
        if (toolbar.getTag() == null) {
            CollapsingToolbarLayout.LayoutParams lp = (CollapsingToolbarLayout.LayoutParams) toolbar.getLayoutParams();
            int statusBarHeight = getStatusBarHeight(activity);
            lp.height += statusBarHeight;
            toolbar.setLayoutParams(lp);
            toolbar.setPadding(toolbar.getPaddingLeft(), toolbar.getPaddingTop() + statusBarHeight, toolbar.getPaddingRight(), toolbar.getPaddingBottom());
            toolbar.setTag(true);
        }

        int statusBarHeight = getStatusBarHeight(activity);
        removeFakeStatusBarViewIfExist(activity);
        removeMarginTopOfContentChild(mContentChild, statusBarHeight);
        final View statusView = addFakeStatusBarView(activity, statusColor, statusBarHeight);

        CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).getBehavior();
        if (behavior != null && behavior instanceof AppBarLayout.Behavior) {
            int verticalOffset = ((AppBarLayout.Behavior) behavior).getTopAndBottomOffset();
            if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
                statusView.setAlpha(1f);
            } else {
                statusView.setAlpha(0f);
            }
        } else {
            statusView.setAlpha(0f);
        }

        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
                    if (statusView.getAlpha() == 0) {
                        statusView.animate().cancel();
                        statusView.animate().alpha(1f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
                    }
                } else {
                    if (statusView.getAlpha() == 1) {
                        statusView.animate().cancel();
                        statusView.animate().alpha(0f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
                    }
                }
            }
        });
    }
}
